package net.seayan.designpattern4j.factory;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.List;
import java.util.Random;

/**
 * 工厂类 用于根据类型构建组件
 * 
 * @ClassName: ModuleFactory
 * @author: yanmeng
 * @date:2012-8-30 上午9:44:30
 */
public class ModuleFactory {

	// 根据指定类型创建组件
	public static IModule createModule(Class<?> clazz) {
		IModule module = null;

		try {
			module = (IModule) Class.forName(clazz.getName()).newInstance();
		} catch (InstantiationException e) {
			System.out.println("未指定任何组件");
		} catch (IllegalAccessException e) {
			System.out.println("不合法的组件类型定义");
		} catch (ClassNotFoundException e) {
			System.out.println("不存在所需定义的组件");
		}
		return module;
	}

	// 随机生成组件
	public static IModule createModule() {
		IModule module = null;
		
		@SuppressWarnings("rawtypes")
		List<Class> concreteModuleList=ClassUtils.getAllClassByInterface(IModule.class);
		
		Random random=new Random();
		int hand=random.nextInt(concreteModuleList.size());
		
		module=createModule(concreteModuleList.get(hand));
		
		return module;
	}

	@SuppressWarnings("all")
	public static class ClassUtils {
		public static List<Class> getAllClassByInterface(Class clazz) {
			List<Class> retClassList = new ArrayList<Class>();

			if (clazz.isInterface()) {

				try {
					String packageName = clazz.getPackage().getName();
					List<Class> allClass = getClasses(packageName);

					for (int i = 0; i < allClass.size(); i++) {
						if (clazz.isAssignableFrom(allClass.get(i))) { // 判断是不是一个接口
							if (!clazz.equals(allClass.get(i))) { // 本身不加进去
								retClassList.add(allClass.get(i));
							}
						}
					}
				} catch (IOException e) {
					e.printStackTrace();
				} catch (ClassNotFoundException e) {
					e.printStackTrace();
				}

			}
			return retClassList;
		}

		public static List<Class> getClasses(String packageName)
				throws IOException, ClassNotFoundException {
			ClassLoader classLoader = Thread.currentThread()
					.getContextClassLoader();
			String path = packageName.replace(".", "/");
			Enumeration<URL> resources = classLoader.getResources(path);
			List<File> dirs = new ArrayList<File>();

			while (resources.hasMoreElements()) {
				URL resource = resources.nextElement();
				dirs.add(new File(resource.getFile()));
			}
			ArrayList<Class> classes = new ArrayList<Class>();
			for (File dir : dirs) {
				classes.addAll(findClasses(dir, packageName));
			}
			return classes;
		}

		private static Collection<? extends Class> findClasses(File dir,
				String packageName) throws ClassNotFoundException {
			List<Class> classes = new ArrayList<Class>();
			if (!dir.exists()) {
				return classes;
			}
			File[] files = dir.listFiles();
			for (File file : files) {
				if (file.isDirectory()) {
					assert !file.getName().contains(".");
					classes.addAll(findClasses(file,
							packageName + "." + file.getName()));
				} else if (file.getName().endsWith(".class")) {
					classes.add(Class.forName(packageName
							+ '.'
							+ file.getName().substring(0,
									file.getName().length() - 6)));
				}
			}
			return classes;
		}
	}

}
